﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace assim
{
    public partial class MainApp : Form
    {
        public MainApp()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Runs the file dialog, and attempts to open the the file
        /// selected, and copies the data into the text area.
        /// </summary>
        private void browseBtn_Click(object sender, EventArgs e)
        {
            if (fileDialog.ShowDialog() == DialogResult.OK)
            {
                filePath.Text = fileDialog.FileName;
                ReadFile();
            }
        }

        /// <summary>
        /// Takes the assembly code and converts it to machine code, and
        /// readies it for execution.
        /// </summary>
        private void assembleBtn_Click(object sender, EventArgs e)
        {
            List<int> data = new List<int>();
            bool success = Assembler.AssembleCode(fileContents.Text, data);
        }

        /// <summary>
        /// Copies the file data into the text area then runs the highlight
        /// text method on the entire text.
        /// </summary>
        private void ReadFile()
        {
            FileStream fin;

            // Open File
            try
            {
                fin = new FileStream(filePath.Text, FileMode.Open);
            }
            catch (FileNotFoundException)
            {
                MessageBox.Show("Error: File '" + Path.GetFileName(filePath.Text) +
                    "' does not exist.", "File not found", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            catch (IndexOutOfRangeException exc)
            { Console.WriteLine(exc.Message + "\nUsage: ShowFile File"); return; }

            // Reset file contents text
            fileContents.Text = "";
            fileContents.SelectionColor = Color.White;
            fileContents.ForeColor = Color.White;

            // read bytes until EOF is encountered 
            int i;
            do
            {
                i = fin.ReadByte();
                if(i == -1 || (char)i == '\r') continue;
                fileContents.Text += (char)i;
            } while (i != -1);

            // Close the file
            fin.Close();

            // Highlight the given text
            HighlightText(0, -1);
        }

        /// <summary>
        /// Highlights the text according to several rules.
        /// </summary>
        public void HighlightText(int start, int end)
        {
            bool isComment = false;
            bool isQuote = false;
            bool wasQuote = false;

            // Scan entire text
            int i = start, j = 0;
            if(end == -1) end = fileContents.Text.Length;
            while(i < end)
            {
                char c = fileContents.Text[i];

                // Highlight current words
                if((!isQuote && (i+1 == end || c == '\n' || c == ' ' || c == ',' || c == '\t' || c == '(' || c == ')')) || 
                   (isQuote && (c == '\"' || c == '\'')))
                {
                    if(isComment)
                    {
                        fileContents.Select(j, i - j + 1);
                        fileContents.SelectionColor = Color.Green;
                    }
                    else if(isQuote)
                    {
                        fileContents.Select(j, i - j + 1);
                        fileContents.SelectionColor = Color.Pink;
                        isQuote = false;
                        wasQuote = true;
                    }
                    else if(fileContents.Text[j] == '$')
                    {
                        if(c == ',' || c == ')')
                            fileContents.Select(j, i - j);
                        else fileContents.Select(j, i - j + 1);
                        fileContents.SelectionColor = Color.Red;
                    }
                    else if(fileContents.Text[j] == '.')
                    {
                        fileContents.Select(j, i - j + 1);
                        fileContents.SelectionColor = Color.Blue;
                    }
                    j = i+1;
                }

                if(c == '\n') isComment = false;
                else if(c == '#') isComment = true;
                else if(!isComment && !wasQuote && (c == '\"' || c == '\'')) isQuote = true;
                wasQuote = false;

                i++;
            }
        }
    }
}
